using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using MinimalistFoodStreet.BackEnd.Infrastructure.Attributes;
using MinimalistFoodStreet.BackEnd.Infrastructure.Dtos.Request.Tables;
using MinimalistFoodStreet.BackEnd.Infrastructure.Dtos.Response;
using MinimalistFoodStreet.BackEnd.Infrastructure.Dtos.Response.Tables;
using MinimalistFoodStreet.BackEnd.Infrastructure.EFCore;
using MinimalistFoodStreet.BackEnd.Server.TableEFCore;
using MinimalistFoodStreet.BackEnd.Server.Server.RequestExtend.Tables;
using MinimalistFoodStreet.BackEnd.Server.Server.ResponseExtend.Tables;
using MinimalistFoodStreet.BackEnd.Server.IServer.Tables;
using System.Security.Cryptography;

namespace MinimalistFoodStreet.BackEnd.Server.Server.Tables
{
    [InjectClass]
    public class OrdersServer : IOrdersServer
    {
        private readonly ServerRepository _serverRepository;
        public OrdersServer(DbContext dbContext)
        {
            _serverRepository = new ServerRepository(dbContext);
        }

        public async Task<ResponseApiDto> AcceptOrder(int id, List<int> odids, List<int> counts, int bid)
        {
            Order order = await _serverRepository.ordersEFCore.Query(d => d.OId == id && d.OBusinessId == bid).SingleOrDefaultAsync();
            if (order == null)
            {
                return ResponseApiDto.Fail("找不到该订单");
            }
            int affectedRows = 0;
            if (order.OStatus != 2)
            {
                return ResponseApiDto.Fail("状态错误");
            }
            if (await _serverRepository.orderDetailsEFCore.Query(d => d.OdOrderId == order.OId).SumAsync(d => d.OdCount) == counts.Sum())
            {
                List<OrderDetail> orderDetails = await _serverRepository.orderDetailsEFCore.Query(d => d.OdOrderId == order.OId).ToListAsync();
                orderDetails.ForEach(d =>
                {
                    int i = odids.FindIndex(e => e == d.OdId);
                    d.OdReceivedCount = i >= 0 ? counts[i] : 0;
                    d.OdReceivedMoney = (int)d.OdReceivedCount * (d.OdPromotePrice != null && d.OdPromotePrice > 0 ? (decimal)d.OdPromotePrice : d.OdPrice);
                });
                order.OStatus = 3;
                order.OCompleteTime = DateTime.Now;
                order.OPayMoney = orderDetails.Sum(d => d.OdReceivedMoney);
                affectedRows += await _serverRepository.ordersEFCore.UpdateAsync(order);
            }
            else
            {
                List<OrderDetail> orderDetails = await _serverRepository.orderDetailsEFCore.Query(d => d.OdOrderId == order.OId).ToListAsync();
                orderDetails.ForEach(d =>
                {
                    int i = odids.FindIndex(e => e == d.OdId);
                    d.OdReceivedCount = i >= 0 ? counts[i] : 0;
                    d.OdReceivedMoney = (int)d.OdReceivedCount * (d.OdPromotePrice != null && d.OdPromotePrice > 0 ? (decimal)d.OdPromotePrice : d.OdPrice);
                });
                order.OStatus = 4;
                order.OCompleteTime = DateTime.Now;
                order.OPayMoney = orderDetails.Sum(d => d.OdReceivedMoney);
                affectedRows += await _serverRepository.ordersEFCore.UpdateAsync(order);
            }
            return ResponseApiDto.Create(affectedRows);
        }

        public async Task<ResponseApiDto> AddAsync(RequestCreateOrdersDto dto, int bid)
        {
            if (dto.goodIds.Count == 0)
            {
                return ResponseApiDto.Fail("请至少选择一个商品");
            }
            List<Good> goods = await _serverRepository.goodsEFCore.Query(d => dto.goodIds.Contains(d.GId)).ToListAsync();
            for (int i = 0; i < goods.Count; i++)
            {
                if (goods[i].GInventory < dto.goodCounts[i])
                {
                    return ResponseApiDto.Fail($"商品{goods[i].GName}库存不足,库存剩余{goods[i].GInventory}");
                }
            }
            if (goods.FindIndex(d => d.GSupplierId != goods[0].GSupplierId) != -1)
            {
                return ResponseApiDto.Fail("商品不属于同一个供应商");
            }
            int affectedRows = 0;
            await _serverRepository.ExecuteInTransactionAsync(async () =>
            {
                List<OrderDetail> orderDetails = new List<OrderDetail>();
                for (int i = 0; i < goods.Count; i++)
                {
                    Good good = goods[i];
                    // 先查询促销信息，只查询一次
                    var promotion = await _serverRepository.promotionsEFCore
                        .Query(d => d.PGoodId == good.GId&&d.PEndTime>DateTime.Now)
                        .FirstOrDefaultAsync();

                    orderDetails.Add(new OrderDetail
                    {
                        OdBirthday = good.GBirthday,
                        OdCount = dto.goodCounts[i],
                        OdDescription = good.GDescription,
                        OdExpiryday = good.GExpiryday,
                        OdGoodId = good.GId,
                        OdIsDirectly = good.GIsDirectly,
                        OdGoodTypeId = good.GGoodTypeId,
                        OdIsPromote = promotion != null ? 1 : 0,
                        OdPromotePrice = promotion?.PDiscountPrice,
                        OdName = good.GName,
                        OdPhoto = good.GPhoto,
                        OdPrice = good.GPrice,
                        OdSupplierId = good.GSupplierId,
                        OdSpecs = good.GSpecs,
                        OdMoney = (promotion?.PDiscountPrice ?? good.GPrice) * dto.goodCounts[i]
                    });
                    good.GInventory-=dto.goodCounts[i];
                }
                Order order = new Order
                {
                    OBusinessId = bid,
                    OOrderId = "",
                    OSupplierId = goods[0].GSupplierId,
                    OStatus = 0,
                    OShouldPayMoney = orderDetails.Sum(d => d.OdMoney)
                };

                affectedRows += await _serverRepository.ordersEFCore.AddAsync(order);
                affectedRows += await _serverRepository.goodsEFCore.UpdateAsync(goods);
                order.OOrderId = "ORD-" + DateTime.Now.Year + "-" + order.OId;
                affectedRows += await _serverRepository.ordersEFCore.UpdateAsync(order);
                orderDetails = orderDetails.Select(d =>
                {
                    d.OdOrderId = order.OId;
                    return d;
                }).ToList();
                affectedRows += await _serverRepository.orderDetailsEFCore.AddAsync(orderDetails);

                // 删除购物车
                if(dto.chartIds!=null)
                affectedRows += await _serverRepository.chartsEFCore.DeleteAsync(_serverRepository.chartsEFCore.Query(d => dto.chartIds.Contains(d.CId)));

            }, () => { affectedRows = 0; return null; });
            return ResponseApiDto.Create(affectedRows);
        }

        public Task<ResponseApiDto> BusinessCancelOrder(int id, int sid)
        {
            throw new NotImplementedException();
        }

        public async Task<ResponseApiDto> DetailAsync(int id)
        {
            ResponseOrdersDto response = await _serverRepository.ordersEFCore.Query(d => d.OId == id).Select(d => new ResponseOrdersDto
            {
                id = d.OId,
                acceptOrderTime = d.OAcceptOrderTime,
                completeTime = d.OCompleteTime,
                sendTime = d.OSendTime,
                payMoney = d.OPayMoney,
                businessId = d.OBusinessId,
                supplierId = d.OSupplierId,
                businessName = d.OBusiness.BName,
                supplierName = d.OSupplier.SShopName,
                status = d.OStatus,
                supplierMarkup = d.OSupplierMarkup,
                businessMarkup = d.OBusinessMarkup,
                details = d.OrderDetails.Select(d => new ResponseOrderDetailDto
                {
                    id = d.OdId,
                    birthday = d.OdBirthday,
                    count = d.OdCount,
                    description = d.OdDescription,
                    expiryDay = d.OdExpiryday,
                    goodId = d.OdGoodId,
                    goodTypeId = d.OdGoodTypeId,
                    isDirectly = d.OdIsDirectly,
                    isPromote = d.OdIsPromote,
                    orderId = d.OdOrderId,
                    name = d.OdName,
                    money = d.OdMoney,
                    photo = d.OdPhoto,
                    price = d.OdPrice,
                    promotePrice = d.OdPromotePrice,
                    receivedCount = d.OdReceivedCount,
                    receivedMoney = d.OdReceivedMoney,
                    specs = d.OdSpecs,
                    supplierId = d.OdSupplierId
                }).ToList()
            }).SingleAsync();
            return ResponseApiDto.Ok("数据已获取", response);
        }

        public Task<ResponseApiDto> GetStatistics()
        {
            throw new NotImplementedException();
        }

        public async Task<ResponseApiDto> PaginationAsync(int page, int limit, string? key, int? bid, int? sid, List<int>? statuss)
        {
            int total = 0;
            List<ResponseOrdersDto> responseOrdersDtos = await _serverRepository.ordersEFCore.Pagination(d => (key == null || d.OrderDetails.Where(d => d.OdName.Contains(key)).Any()|| d.OBusiness.BName.Contains(key)|| d.OSupplier.SShopName.Contains(key)) && (bid == null || d.OBusinessId == bid) && (sid == null || d.OSupplierId == sid) && (statuss == null || statuss.Contains(d.OStatus)), false, d => d.OId, out total, page, limit).Select(d => new ResponseOrdersDto
            {
                id = d.OId,
                orderId = d.OOrderId,
                acceptOrderTime = d.OAcceptOrderTime,
                completeTime = d.OCompleteTime,
                sendTime = d.OSendTime,
                businessName = d.OBusiness.BName,
                supplierName = d.OSupplier.SShopName,
                shouldPayMoney = (decimal)d.OShouldPayMoney,
                payMoney = d.OPayMoney,
                businessId = d.OBusinessId,
                supplierId = d.OSupplierId,
                status = d.OStatus,
                supplierMarkup = d.OSupplierMarkup,
                businessMarkup = d.OBusinessMarkup,
                createtime = d.OCreateTime,
                details = d.OrderDetails.Select(d => new ResponseOrderDetailDto
                {
                    id = d.OdId,
                    birthday = d.OdBirthday,
                    count = d.OdCount,
                    description = d.OdDescription,
                    expiryDay = d.OdExpiryday,
                    goodId = d.OdGoodId,
                    goodTypeId = d.OdGoodTypeId,
                    isDirectly = d.OdIsDirectly,
                    isPromote = d.OdIsPromote,
                    orderId = d.OdOrderId,
                    name = d.OdName,
                    money = d.OdMoney,
                    photo = d.OdPhoto,
                    price = d.OdPrice,
                    promotePrice = d.OdPromotePrice,
                    receivedCount = d.OdReceivedCount,
                    receivedMoney = d.OdReceivedMoney,
                    specs = d.OdSpecs,
                    supplierId = d.OdSupplierId
                }).ToList()
            }).ToListAsync();
            responseOrdersDtos.ForEach(d =>
            {
                d.acceptOrderTimeStr = d.acceptOrderTime != null ? ((DateTime)d.acceptOrderTime).ToString("yyyy-MM-dd HH:mm:ss") : null;
                d.completeTimeStr = d.completeTime != null ? ((DateTime)d.completeTime).ToString("yyyy-MM-dd HH:mm:ss") : null;
                d.receiveTimeStr = d.receiveTime != null ? ((DateTime)d.receiveTime).ToString("yyyy-MM-dd HH:mm:ss") : null;
                d.sendTimeStr = d.sendTime != null ? ((DateTime)d.sendTime).ToString("yyyy-MM-dd HH:mm:ss") : null;
                d.createtimeStr = d.createtime.ToString("yyyy-MM-dd HH:mm:ss");
            });
            return ResponseApiDto.Ok("数据已获取", new { data = responseOrdersDtos, total = total });
        }

        public Task<ResponseApiDto> RefuseAcceptOrder(int id, int bid)
        {
            throw new NotImplementedException();
        }

        public Task<ResponseApiDto> RefuseTakeOrder(int id, int sid)
        {
            throw new NotImplementedException();
        }

        public async Task<ResponseApiDto> Shipment(int id, int sid)
        {
            Order order = await _serverRepository.ordersEFCore.Query(d => d.OId == id && d.OSupplierId == sid).SingleOrDefaultAsync();
            int affectedRows = 0;
            if (order != null && order.OStatus == 1)
            {
                order.OStatus = 2;
                order.OSendTime = DateTime.Now;
                affectedRows += await _serverRepository.ordersEFCore.UpdateAsync(order);
            }
            return ResponseApiDto.Create(affectedRows);
        }

        public Task<ResponseApiDto> SupplierCancelOrder(int id, int sid)
        {
            throw new NotImplementedException();
        }

        public async Task<ResponseApiDto> TakeOrder(int id, int sid)
        {
            Order order = await _serverRepository.ordersEFCore.Query(d => d.OId == id && d.OSupplierId == sid).SingleOrDefaultAsync();
            int affectedRows = 0;
            if (order != null && order.OStatus == 0)
            {
                order.OStatus = 1;
                order.OAcceptOrderTime = DateTime.Now;
                affectedRows += await _serverRepository.ordersEFCore.UpdateAsync(order);
            }
            return ResponseApiDto.Create(affectedRows);
        }



    }
}